package edu.temple.templepatco;

import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.TextView;

/**
 * This is the starting point for the App and creates the UI
 */
public class MainActivity extends Activity {
	private ExpandableListView mainList;
	private ExpandableListAdapter mainListAdaptor;
	private TextView mainTextView;
	private ArrayList<Route> theRoutes;
	private Handler mHandler;
	private Calendar lastRequest;

	/**
	 * This creates the activity when the App is first launched and immediately
	 * calls refresh after the UI is built
	 * 
	 * @param savedInstanceState
	 */
	public void onCreate(Bundle savedInstanceState) {
		// create the main view
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// Create the list view and text view
		mainList = (ExpandableListView) findViewById(R.id.primaryRouteExpandableListView);
		mainTextView = (TextView) findViewById(R.id.Output);
		// Create a resorce object
		Resources standardResources = getResources();
		DisplayMetrics metrics = standardResources.getDisplayMetrics();
		Configuration config = standardResources.getConfiguration();
		Resources res = new Resources(standardResources.getAssets(), metrics, config);
		InputStream instream = res.openRawResource(R.raw.east_wkday_combined);
		ArrayList<Stop[]> oneDay = Router.readPATCOSchedule(instream);
		for (int i = Calendar.MONDAY; i <= Calendar.FRIDAY; i++) {
			Router.setPATCOSchedule(oneDay, i);
		}
		instream = res.openRawResource(R.raw.east_sat);
		oneDay = Router.readPATCOSchedule(instream);
		Router.setPATCOSchedule(oneDay, Calendar.SATURDAY);
		instream = res.openRawResource(R.raw.east_sun);
		oneDay = Router.readPATCOSchedule(instream);
		Router.setPATCOSchedule(oneDay, Calendar.SUNDAY);
		theRoutes = new ArrayList<Route>();

		refresh(null);
	}

	/**
	 * Creates a new MyExpandableListAdapter
	 * 
	 * @return ExpandableListAdapter
	 */
	private ExpandableListAdapter buildListAdaptor() {
		return new myExpandableListAdaptor();
	}

	/**
	 * This function will update the list of routes based on the current time
	 * and update the UI to reflect any changes
	 * 
	 * @param v
	 *            (A view parameter is required by the API but the value is
	 *            ignored)
	 */
	public void refresh(View v) {

		if (isNetworkConnected()) {
			mHandler = new Handler();
			Thread t = new Thread() {
				/**
				 * This function will be run when the tread t is started
				 * 
				 * @return void
				 * @author Adam Pasqua Blaisse and James Robison
				 * @Version 7/26/2012
				 */
				public void run() {
					Log.i("Temple-PATCO", "Refreshing route list");
					try {
						// for now we only want to keep one set of old results
						for (int i = theRoutes.size() - 1; i >= 0; i--) {
							// delete any routes not from the most recent
							// refresh
							if (!theRoutes.get(i).getRequestTime().equals(lastRequest.getTime())) {
								theRoutes.remove(i);
							}
						}
						// set the time for the current refresh
						lastRequest = Calendar.getInstance();
						theRoutes.addAll(Router.findRoute(lastRequest));
						Collections.sort(theRoutes);
					} catch (ParseException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					mHandler.post(new Runnable() {
						public void run() {
							for (Route r : theRoutes) {
								if (r.toString() != null) {
									Log.i("Temple-PATCO", r.toString());
								} else {
									Log.i("Temple-PATCO", "This Route Is Null, You Are Obviously Drunk....");
								}
							}
							mainListAdaptor = buildListAdaptor();
							mainList.setAdapter(mainListAdaptor);
							if (theRoutes.size() > 0) {
								mainTextView.setText(null);
								mainTextView.setVisibility(View.GONE);
							} else {
								mainTextView.setText("No routes found");
								mainTextView.setVisibility(View.VISIBLE);
							}
						}
					});
				}
			};
			t.start();
		} else {
			mainTextView.setText("The network appears to be down, coudln't refresh");
			mainTextView.setVisibility(View.VISIBLE);
		}
	}

	/**
	 * This function will determine if both WiFi and mobile data are disabled
	 * and return the result as a boolean where true is means at least one is
	 * enabled
	 * 
	 * @return boolean (This value will be true if the network is enabled)
	 */
	private boolean isNetworkConnected() {
		ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo ni = cm.getActiveNetworkInfo();
		if (ni == null) {
			// There are no active networks.
			return false;
		} else
			return true;
	}

	/**
	 * This class is our variant on the BaseExpandableListAdapter
	 * 
	 * @author Adam Pasqua Blaisse and James Robison
	 */
	private class myExpandableListAdaptor extends BaseExpandableListAdapter {
		/**
		 * This is the default Constructor for a myExpandableListAdaptor
		 */
		public myExpandableListAdaptor() {
			if (theRoutes == null) {
				theRoutes = new ArrayList<Route>();
			}
		}

		/**
		 * This function will setup and return a Generic Text View
		 * 
		 * @return TextView
		 */
		public TextView getGenericView() {
			// Layout parameters for the ExpandableListView
			AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 64);

			TextView textView = new TextView(MainActivity.this);
			textView.setLayoutParams(lp);
			// Center the text vertically
			textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
			// Set the text starting position
			textView.setPadding(0, 0, 14, 0);
			return textView;
		}

		/**
		 * This function will get the child
		 * 
		 * @return Object
		 */
		public Object getChild(int groupPosition, int childPosition) {
			return theRoutes.get(groupPosition).getStops()[childPosition];
		}

		/**
		 * This function will get the Child ID
		 * 
		 * @return Long childPosition
		 * @param groupPosition
		 * @param childPosition
		 */
		public long getChildId(int groupPosition, int childPosition) {
			return childPosition;
		}

		/**
		 * This function will get the child view
		 * 
		 * @return View
		 * @param groupPosition
		 * @param childPosition
		 * @param isLastChild
		 * @param convertView
		 * @param parent
		 */
		public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
				ViewGroup parent) {
			TextView textView = getGenericView();
			textView.setText(getChild(groupPosition, childPosition).toString());
			return textView;
		}

		/**
		 * This function will return the number of children
		 * 
		 * @return int
		 * @param groupPosition
		 */
		public int getChildrenCount(int groupPosition) {
			return theRoutes.get(groupPosition).getStops().length;
		}

		/**
		 * This function will get the group
		 * 
		 * @return Object
		 * @param groupPosition
		 */
		public Object getGroup(int groupPosition) {
			return theRoutes.get(groupPosition).getLabel();
		}

		/**
		 * This function will get the number of groups
		 * 
		 * @return int
		 */
		public int getGroupCount() {
			return theRoutes.size();
		}

		/**
		 * This function will get the group's ID
		 * 
		 * @return long
		 * @param groupPosition
		 */
		public long getGroupId(int groupPosition) {
			return groupPosition;
		}

		/**
		 * This function will get the groups view
		 * 
		 * @return View
		 * @param groupPosition
		 * @param isExpanded
		 * @param convertView
		 * @param parent
		 */
		public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
			TextView textView = getGenericView();

			Route r = theRoutes.get(groupPosition);
			if (r.getRequestTime().equals(lastRequest.getTime())) {
				textView.setText(r.getLabel().toString());
				textView.setBackgroundColor(Color.BLACK);
			} else {
				textView.setText("(OLD)" + r.getLabel().toString());
				textView.setBackgroundColor(Color.GRAY);
			}
			textView.setTextColor(Color.WHITE);
			return textView;
		}

		/**
		 * This function will check for stable ID's
		 * 
		 * @return boolean
		 */
		public boolean hasStableIds() {
			return false;
		}

		/**
		 * This function will return if a child is selectable
		 * 
		 * @return boolean
		 * @param groupPosition
		 * @param childPosition
		 */
		public boolean isChildSelectable(int groupPosition, int childPosition) {
			return false;
		}
	}

}
